﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using BobcatUtility;
using Amib.Threading;

namespace CNUtility
{
    /// <summary>
    /// This class registers for events from the singleton Logger log-broker, and
    /// writes the events to a file. The file writing is done on a background thread.
    /// </summary>
    public class LogFileLogger
    {
        #region Public methods

        /// <summary>
        /// Constructor.
        /// </summary>
        public LogFileLogger(string strFilename)
        {
            m_File = new StreamWriter(strFilename);
            Logger.MessageLoggedEvent += onMessageLogged;
        }

        /// <summary>
        /// Closes the log file and cleans up.
        /// </summary>
        public void close()
        {
            // We make sure that the background thread has finished processing
            // before closing...
            m_ThreadPool.WaitForIdle(WAIT_FOR_IDLE_TIMEOUT);
            Logger.MessageLoggedEvent -= onMessageLogged;
            m_File.Close();
        }

        #endregion

        #region Private functions

        /// <summary>
        /// Called when a message has been logged.
        /// </summary>
        private void onMessageLogged(object sender, Logger.Args e)
        {
            // We write the message to the queue for the background thread...
            string strMessage = e.Level.ToString() + ": " + e.Message;
            m_ThreadPool.QueueWorkItem(processQueuedItem, strMessage);
        }

        /// <summary>
        /// Called on the worker thread to log the message passed in to
        /// the file.
        /// </summary>
        private object processQueuedItem(object state)
        {
            string strMessage = (string)state;
            m_File.WriteLine(strMessage);
            m_File.Flush();

            return null;
        }

        #endregion

        #region Private data

        private StreamWriter m_File = null;

        // This thread-pool lets us process DB requests and updates on a background thread.
        // Despite being a 'pool' it just manages one thread, as we want to make sure that
        // queued updates are applied to the DB in the order they were added to the queue...
        private const int THREAD_RECOVERY_TIMEOUT = 10000;
        private const int WAIT_FOR_IDLE_TIMEOUT = 5000;
        private SmartThreadPool m_ThreadPool = new SmartThreadPool(THREAD_RECOVERY_TIMEOUT, 1);

        #endregion
    }
}
